home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / plan / src / help.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  7KB  |  245 lines

  1. /*
  2.  * print help popup on a particular topic. Help topics are identified by
  3.  * a short string that is looked up in the help file. The help file contains
  4.  * a list of button help entries; each consisting of a line "%% topic"
  5.  * followed by help text lines. Leading blanks in text lines are ignored.
  6.  * Lines beginning with '#' are ignored.
  7.  *
  8.  * To add a help text to a widget, call
  9.  *    XtAddCallback(widget, XmNhelpCallback, help_callback, "topic")
  10.  * and add "%%n topic" and the help text to the help file (n is a number
  11.  * used for extracting a user's manual, it is not used by the plan program).
  12.  *
  13.  * help_callback(parent, topic)        Print help for a topic, usually for
  14.  *                    button <parent>.
  15.  */
  16.  
  17. #include <stdio.h>
  18. #include <Xm/Xm.h>
  19. #include <Xm/DialogS.h>
  20. #include <Xm/Form.h>
  21. #include <Xm/Frame.h>
  22. #include <Xm/LabelP.h>
  23. #include <Xm/LabelG.h>
  24. #include <Xm/PushBP.h>
  25. #include <Xm/PushBG.h>
  26. #include <Xm/ToggleB.h>
  27. #include <Xm/Text.h>
  28. #include <Xm/Protocols.h>
  29. #include <X11/cursorfont.h>
  30. #include "cal.h"
  31.  
  32. static void        done_callback(), context_callback();
  33. static char        *get_text();
  34. extern void        *malloc(), *realloc();
  35. extern BOOL        find_file();
  36.  
  37. extern Display        *display;    /* everybody uses the same server */
  38. extern XFontStruct    *font[NFONTS];    /* fonts: FONT_* */
  39. extern Pixel        color[NCOLS];    /* colors: COL_* */
  40.  
  41. static BOOL        have_shell;    /* message popup exists if TRUE */
  42. static Widget        shell;        /* popup menu shell */
  43.  
  44.  
  45. /*
  46.  * destroy the help popup. Remove it from the screen, and destroy its widgets.
  47.  */
  48.  
  49. destroy_help_popup()
  50. {
  51.     if (have_shell) {
  52.         XtPopdown(shell);
  53.         XTDESTROYWIDGET(shell);
  54.         have_shell = FALSE;
  55.     }
  56. }
  57.  
  58.  
  59.  
  60. /*
  61.  * look up the help text for <topic> and create a window containing the text.
  62.  */
  63.  
  64. /*ARGSUSED*/
  65. void help_callback(parent, topic)
  66.     Widget            parent;
  67.     char            *topic;
  68. {
  69.     static BOOL        have_fontlist;
  70.     static XmFontList    fontlist;
  71.     static Widget        text_w;
  72.     Widget            form, w;
  73.     Atom            closewindow;
  74.     char            *message;
  75.     Arg            args[20];
  76.     int            n;
  77.     int            nlines = 1;
  78.     char            *p;
  79.  
  80.     if (!(message = get_text(topic)))
  81.         return;
  82.     if (have_shell) {
  83.         XmTextSetString(text_w, message);
  84.         XtPopup(shell, XtGrabNone);
  85.         return;
  86.     }
  87.     if (!have_fontlist++)
  88.         fontlist = XmFontListCreate(font[FONT_HELP], "cset");
  89.     for (nlines=0, p=message; *p; p++)
  90.         nlines += *p == '\n';
  91.     if (nlines > 30)
  92.         nlines = 30;
  93.  
  94.     n = 0;
  95.     XtSetArg(args[n], XmNdeleteResponse,    XmDO_NOTHING);        n++;
  96.     XtSetArg(args[n], XmNiconic,        False);            n++;
  97.     shell = XtAppCreateShell("Help", "plan",
  98.             applicationShellWidgetClass, display, args, n);
  99. #    ifdef EDITRES
  100.     XtAddEventHandler(shell, (EventMask)0, TRUE, 
  101.              _XEditResCheckMessages, NULL);
  102. #    endif
  103.     set_icon(shell, 1);
  104.     form = XtCreateManagedWidget("helpform", xmFormWidgetClass,
  105.             shell, NULL, 0);
  106.     XtAddCallback(form, XmNhelpCallback, (XtCallbackProc)help_callback,
  107.                             (XtPointer)"help");
  108.  
  109.                             /*-- buttons --*/
  110.     n = 0;
  111.     XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  112.     XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  113.     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  114.     XtSetArg(args[n], XmNrightOffset,    8);            n++;
  115.     XtSetArg(args[n], XmNwidth,        80);            n++;
  116.     w = XtCreateManagedWidget("Dismiss", xmPushButtonWidgetClass,
  117.             form, args, n);
  118.     XtAddCallback(w, XmNactivateCallback, done_callback, (XtPointer)0);
  119.     XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)help_callback,
  120.                         (XtPointer)"help_done");
  121.     n = 0;
  122.     XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  123.     XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  124.     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_WIDGET);    n++;
  125.     XtSetArg(args[n], XmNrightWidget,    w);            n++;
  126.     XtSetArg(args[n], XmNrightOffset,    8);            n++;
  127.     XtSetArg(args[n], XmNwidth,        80);            n++;
  128.     w = XtCreateManagedWidget("Context", xmPushButtonWidgetClass,
  129.             form, args, n);
  130.     XtAddCallback(w, XmNactivateCallback, context_callback, (XtPointer)0);
  131.     XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)help_callback,
  132.                             (XtPointer)"help");
  133.  
  134.                             /*-- text --*/
  135.     n = 0;
  136.     XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  137.     XtSetArg(args[n], XmNtopOffset,        8);            n++;
  138.     XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_WIDGET);    n++;
  139.     XtSetArg(args[n], XmNbottomWidget,    w);            n++;
  140.     XtSetArg(args[n], XmNbottomOffset,    16);            n++;
  141.     XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  142.     XtSetArg(args[n], XmNleftOffset,    8);            n++;
  143.     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  144.     XtSetArg(args[n], XmNrightOffset,    8);            n++;
  145.     XtSetArg(args[n], XmNhighlightThickness,0);            n++;
  146.     XtSetArg(args[n], XmNeditable,        False);            n++;
  147.     XtSetArg(args[n], XmNeditMode,        XmMULTI_LINE_EDIT);    n++;
  148.     XtSetArg(args[n], XmNcolumns,        60);            n++;
  149.     XtSetArg(args[n], XmNrows,        nlines+1);        n++;
  150.     XtSetArg(args[n], XmNfontList,        fontlist);        n++;
  151.     XtSetArg(args[n], XmNscrollVertical,    True);            n++;
  152.     XtSetArg(args[n], XmNpendingDelete,    False);            n++;
  153.     text_w = w = XmCreateScrolledText(form, "text", args, n);
  154.     XmTextSetString(w, message);
  155.     XtManageChild(w);
  156.     XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)help_callback,
  157.                             (XtPointer)"help");
  158.  
  159.     XtPopup(shell, XtGrabNone);
  160.     closewindow = XmInternAtom(display, "WM_DELETE_WINDOW", False);
  161.     XmAddWMProtocolCallback(shell, closewindow,
  162.                     done_callback, (XtPointer)shell);
  163.     have_shell = TRUE;
  164.     free(message);
  165. }
  166.  
  167.  
  168. /*ARGSUSED*/
  169. static void done_callback(widget, item, data)
  170.     Widget                widget;
  171.     int                item;
  172.     XmToggleButtonCallbackStruct    *data;
  173. {
  174.     destroy_help_popup();
  175. }
  176.  
  177.  
  178. /*ARGSUSED*/
  179. static void context_callback(widget, item, data)
  180.     Widget                widget;
  181.     int                item;
  182.     XmToggleButtonCallbackStruct    *data;
  183. {
  184.     Widget w;
  185.     Cursor cursor = XCreateFontCursor(display, XC_question_arrow);
  186.     if (w = XmTrackingLocate(shell, cursor, False)) {
  187.         data->reason = XmCR_HELP;
  188.         XtCallCallbacks(w, XmNhelpCallback, &data);
  189.     }
  190.     XFreeCursor(display, cursor);
  191. }
  192.  
  193.  
  194. /*ARGSUSED*/
  195. static char *get_text(topic)
  196.     char            *topic;
  197. {
  198.     FILE            *fp;        /* help file */
  199.     char            line[1024];    /* line buffer (and filename)*/
  200.     char            *text;        /* text buffer */
  201.     int            textsize;    /* size of text buffer */
  202.     int            textlen = 0;    /* # of chars in text buffer */
  203.     int            n;        /* for stripping trailing \n */
  204.     register char        *p;
  205.  
  206.     if (!(text = (char *)malloc(textsize = 4096)))
  207.         return(0);
  208.     *text = 0;
  209.     if (!find_file(line, HELP_FN, FALSE) || !(fp = fopen(line, "r"))) {
  210.         sprintf(text, "Sorry, no help available,\n%s not found",
  211.                                 HELP_FN);
  212.         return(text);
  213.     }
  214.     for (;;) {                    /* find topic */
  215.         if (!fgets(line, 1024, fp)) {
  216.             strcpy(text, "Sorry, no help available");
  217.             return(text);
  218.         }
  219.         if (line[0] != '%' || line[1] != '%')
  220.             continue;
  221.         line[strlen(line)-1] = 0; /* strip \n */
  222.         for (p=line+2; *p >= '0' && *p <= '9'; p++);
  223.         for (; *p == ' ' || *p == '\t'; p++);
  224.         if (*p && *p != '\n' && !strcmp(p, topic))
  225.             break;
  226.     }
  227.     for (;;) {                    /* read text */
  228.         if (!fgets(line, 1024, fp))
  229.             break;
  230.         if (line[0] == '#')
  231.             continue;
  232.         if (line[0] == '%' && line[1] == '%')
  233.             return(text);
  234.         p = line[0] == '\t' ? line+1 : line;
  235.         if (textlen + strlen(p) > textsize)
  236.             if (!(text = (char *)realloc(text, textsize += 4096)))
  237.                 break;
  238.         strcat(text, p);
  239.         textlen += strlen(p);
  240.     }
  241.     for (n=strlen(text); n && text[n-1] == '\n'; n--)
  242.         text[n-1] = 0;
  243.     return(text);
  244. }
  245.